package com.sne.common.task;

import com.alibaba.fastjson.JSONObject;
import com.sne.common.constant.ScheduleConstants;
import com.sne.monitor.entity.MonitorTimeTask;
import com.sne.monitor.entity.MonitorTimeTaskLog;
import com.sne.sys.service.ISysDictItemService;
import com.sne.sys.vo.SysDictItemVO;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.ZoneOffset;

/**
 * 抽象quartz 调用
 * @author fanghh
 * @date 2020/12/11
 */
@Component
@Slf4j
public abstract class AbstractQuartzJob implements Job {

    @Autowired
    private KafkaTemplate kafkaTemplate;

    @Autowired
    private ISysDictItemService dictItemService;

    @Autowired
    private RedisTemplate redisTemplate;


    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        MonitorTimeTask timeTask = new MonitorTimeTask();
        BeanUtils.copyProperties(context.getMergedJobDataMap()
                .get(ScheduleConstants.TASK_PROPERTIES),timeTask);
        try {
            before(context,timeTask);
            doExecute(context,timeTask);
            after(context,timeTask,null);
        }catch (Exception e){
            log.error("任务执行异常：",e);
            after(context,timeTask,e);
        }

    }

    protected void before(JobExecutionContext context,MonitorTimeTask timeTask){
        redisTemplate.opsForValue().set(ScheduleConstants.TASK_CLASS_NAME+timeTask.getId(),
                LocalDateTime.now().toString());
    }

    protected void after(JobExecutionContext context,MonitorTimeTask timeTask,Exception e){
        String timeStr = (String) redisTemplate.opsForValue().get(ScheduleConstants.TASK_CLASS_NAME+timeTask.getId());
        LocalDateTime time = LocalDateTime.parse(timeStr);
        redisTemplate.delete(ScheduleConstants.TASK_CLASS_NAME+timeTask.getId());
        MonitorTimeTaskLog taskLog = new MonitorTimeTaskLog();
        taskLog.setTaskName(timeTask.getTaskName())
                .setTaskFunc(timeTask.getTaskFun())
                .setEndTime(LocalDateTime.now())
                .setCreateTime(time);
        SysDictItemVO itemVO = dictItemService.findDictItemCode("time_task_group", timeTask.getTaskGroup());
        if(itemVO != null){
            taskLog.setTaskGroup(itemVO.getItemName());
        }
        long end = taskLog.getEndTime().toEpochSecond(ZoneOffset.UTC);
        long start = time.toEpochSecond(ZoneOffset.UTC);
        taskLog.setExcuteTime(end-start);
        taskLog.setMessage(taskLog.getTaskName()+" 总共耗时："+(end-start)+"毫秒");
        if(e != null){
            taskLog.setState("失败");
            taskLog.setExceptionInfo(e.getMessage());
        }else{
            taskLog.setState("成功");
        }
        try {
            kafkaTemplate.send("monitor-task", JSONObject.toJSONString(taskLog));
        } catch (Exception ex) {
            log.error("kafka生产异常:", ex);
        }
    }

    /**
     * 执行方法，子类重载
     * @param context 工作执行上下文
     * @param timeTask 定时任务
     */
    protected abstract void doExecute(JobExecutionContext context,MonitorTimeTask timeTask) throws Exception;
}
